import socket
import struct
-def readlines(fd):
+def _readlines(fd):
"""Version of readlines safe against EINTR.
"""
import errno
lines.append(line)
return lines
-def readline(fd):
+def _readline(fd):
"""Version of readline safe against EINTR.
"""
while 1:
NBE_BRIDGE = 'nbe-br'
def get_current_ipaddr(dev='eth0'):
- """Return a string containing the primary IP address for the given
- network interface (default 'eth0').
+ """Get the primary IP address for the given network interface.
+
+ dev network interface (default eth0)
+
+ returns interface address as a string
"""
fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- lines = readlines(fd)
+ lines = _readlines(fd)
for line in lines:
m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
line )
return None
def get_current_ipmask(dev='eth0'):
- """Return a string containing the primary IP netmask for the given
- network interface (default 'eth0').
+ """Get the primary IP netmask for a network interface.
+
+ dev network interface (default eth0)
+
+ returns interface netmask as a string
"""
fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- lines = readlines(fd)
+ lines = _readlines(fd)
for line in lines:
m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
line )
return None
def get_current_ipgw(dev='eth0'):
- """Return a string containing the IP gateway for the given
- network interface (default 'eth0').
+ """Get the IP gateway for a network interface.
+
+ dev network interface (default eth0)
+
+ returns gateway address as a string
"""
fd = os.popen( '/sbin/route -n' )
- lines = readlines(fd)
+ lines = _readlines(fd)
for line in lines:
m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
'\s+\S+\s+\S*G.*' + dev + '.*', line )
def inet_aton(addr):
"""Convert an IP addr in IPv4 dot notation into an int.
+
+ addr IP address as a string
+
+ returns integer
"""
b = socket.inet_aton(addr)
return struct.unpack('!I', b)[0]
def inet_ntoa(n):
"""Convert an int into an IP addr in IPv4 dot notation.
+
+ n IP address
+
+ returns string
"""
b = struct.pack('!I', n)
return socket.inet_ntoa(b)
def add_offset_to_ip(addr, offset):
"""Add a numerical offset to an IP addr in IPv4 dot notation.
+
+ addr IP address
+ offset offset to add
+
+ returns new address
"""
n = inet_aton(addr)
n += offset
return inet_ntoa(n)
def check_subnet( ip, network, netmask ):
+ """Check if an IP address is in the subnet defined by
+ a network address and mask'.
+
+ ip IP adress
+ network network address
+ netmask network mask
+
+ returns 1 if it is in the subnet, 0 if not
+ """
n_ip = inet_aton(ip)
n_net = inet_aton(network)
n_mask = inet_aton(netmask)
from xen.xm.opts import *
-gopts = Opts(use="""[options]
+gopts = Opts(use="""[options] [vars]
Create a domain.
fn=set_value, default=None,
use='Domain saved state to load.')
-#gopts.opt('define', short='D', val='VAR=VAL',
-# fn=set_var, default=None,
-# use="""Set a variable before loading defaults, e.g. '-D vmid=3'
-# to set vmid. May be repeated to set more than one variable.""")
-
gopts.opt('dryrun', short='n',
fn=set_true, default=0,
use="""Dry run - print the config but don't create the domain.
The defaults file is loaded and the SXP configuration is created and printed.
""")
-gopts.opt('name', short='N', val='NAME',
- fn=set_value, default=None,
- use="Domain name.")
-
gopts.opt('console_autoconnect', short='c',
fn=set_true, default=0,
use="Connect to console after domain is created.")
-gopts.opt('kernel', short='k', val='FILE',
+gopts.var('name', val='NAME',
+ fn=set_value, default=None,
+ use="Domain name.")
+
+gopts.var('kernel', val='FILE',
fn=set_value, default=None,
use="Path to kernel image.")
-gopts.opt('ramdisk', short='r', val='FILE',
+gopts.var('ramdisk', val='FILE',
fn=set_value, default='',
use="Path to ramdisk.")
-gopts.opt('builder', short='b', val='FUNCTION',
+gopts.var('builder', val='FUNCTION',
fn=set_value, default='linux',
use="Function to use to build the domain.")
-gopts.opt('memory', short='m', val='MEMORY',
+gopts.var('memory', val='MEMORY',
fn=set_value, default=128,
use="Domain memory in MB.")
-gopts.opt('autorestart',
- fn=set_true, default=0,
+gopts.var('autorestart', val='no|yes',
+ fn=set_bool, default=0,
use="Whether to restart the domain on exit.")
-gopts.opt('blkif',
- fn=set_true, default=0,
+gopts.var('blkif', val='no|yes',
+ fn=set_bool, default=0,
use="Make the domain a block device backend.")
-gopts.opt('netif',
- fn=set_true, default=0,
+gopts.var('netif', val='no|yes',
+ fn=set_bool, default=0,
use="Make the domain a network interface backend.")
-gopts.opt('disk', short='d', val='phy:DEV,VDEV,MODE',
+gopts.var('disk', val='phy:DEV,VDEV,MODE',
fn=append_value, default=[],
use="""Add a disk device to a domain. The physical device is DEV,
which is exported to the domain as VDEV. The disk is read-only if MODE
The option may be repeated to add more than one disk.
""")
-gopts.opt('pci', val='BUS,DEV,FUNC',
+gopts.var('pci', val='BUS,DEV,FUNC',
fn=append_value, default=[],
use="""Add a PCI device to a domain, using given params (in hex).
For example '-pci c0,02,1a'.
The option may be repeated to add more than one pci device.
""")
-gopts.opt('ipaddr', short='i', val="IPADDR",
+gopts.var('ipaddr', val="IPADDR",
fn=append_value, default=[],
use="Add an IP address to the domain.")
-gopts.opt('vif', val="mac=MAC,bridge=BRIDGE",
+gopts.var('vif', val="mac=MAC,bridge=BRIDGE",
fn=append_value, default=[],
use="""Add a network interface with the given MAC address and bridge.
If mac is not specified a random MAC address is used.
Specifying vifs will increase the number of interfaces as needed.
""")
-gopts.opt('nics', val="NUM",
+gopts.var('nics', val="NUM",
fn=set_int, default=1,
use="""Set the number of network interfaces.
Use the vif option to define interface parameters, otherwise
number of interfaces as needed.
""")
-gopts.opt('root', short='R', val='DEVICE',
+gopts.var('root', val='DEVICE',
fn=set_value, default='',
use="""Set the root= parameter on the kernel command line.
Use a device, e.g. /dev/sda1, or /dev/nfs for NFS root.""")
-gopts.opt('extra', short='E', val="ARGS",
+gopts.var('extra', val="ARGS",
fn=set_value, default='',
use="Set extra arguments to append to the kernel command line.")
-gopts.opt('ip', short='I', val='IPADDR',
+gopts.var('ip', val='IPADDR',
fn=set_value, default='',
use="Set the kernel IP interface address.")
-gopts.opt('gateway', val="IPADDR",
+gopts.var('gateway', val="IPADDR",
fn=set_value, default='',
use="Set the kernel IP gateway.")
-gopts.opt('netmask', val="MASK",
+gopts.var('netmask', val="MASK",
fn=set_value, default = '',
use="Set the kernel IP netmask.")
-gopts.opt('hostname', val="NAME",
+gopts.var('hostname', val="NAME",
fn=set_value, default='',
use="Set the kernel IP hostname.")
-gopts.opt('interface', val="INTF",
+gopts.var('interface', val="INTF",
fn=set_value, default="eth0",
use="Set the kernel IP interface name.")
-gopts.opt('dhcp', val="off|dhcp",
+gopts.var('dhcp', val="off|dhcp",
fn=set_value, default='off',
use="Set the kernel dhcp option.")
-gopts.opt('nfs_server', val="IPADDR",
+gopts.var('nfs_server', val="IPADDR",
fn=set_value, default=None,
use="Set the address of the NFS server for NFS root.")
-gopts.opt('nfs_root', val="PATH",
+gopts.var('nfs_root', val="PATH",
fn=set_value, default=None,
use="Set the path of the root NFS directory.")
d = {}
a = vif.split(',')
for b in a:
- (k, v) = b.strip().split('=')
+ (k, v) = b.strip().split('=', 1)
k = k.strip()
v = v.strip()
if k not in ['mac', 'bridge']:
# Process remaining args as config variables.
for arg in args:
if '=' in arg:
- (var, val) = arg.strip().split('=')
+ (var, val) = arg.strip().split('=', 1)
gopts.setvar(var.strip(), val.strip())
if opts.vals.config:
pass
"""
return self.specified_opt
+class OptVar(Opt):
+ """An individual option variable.
+ """
+ def __init__(self, opts, name,
+ val=None, fn=None, use=None, default=None):
+ """Create an option.
+
+ opts parent options object
+ name name of the field it controls
+ val string used to print option args in help.
+ If val is not specified the option has no arg.
+ fn function to call when the option is specified.
+ use usage (help) string
+ default default value if not specified on command-line
+ """
+ if val is None:
+ val = name.upper()
+ Opt.__init__(self, opts, name, val=val, fn=fn, use=use, default=default)
+ self.optkeys = []
+ self.optkeys.append(self.long)
+
+ def short_opt(self):
+ return None
+
+ def long_opt(self):
+ return None
+
+ def show(self):
+ print '%s=%s' %(self.optkeys[0], self.val)
+ print
+ if self.use:
+ print '\t',
+ print self.use
+ if self.val:
+ print '\tDefault', self.default or 'None'
+
class OptVals:
"""Class to hold option values.
"""
class Opts:
"""Container for options.
"""
+
+ imports = ["import sys",
+ "import os",
+ "import os.path",
+ "from xen.util.ip import *",
+ ]
+
def __init__(self, use=None):
"""Options constructor.
self.options_map[name] = x
return x
+ def var(self, name, **args):
+ x = OptVar(self, name, **args)
+ self.options.append(x)
+ self.options_map[name] = x
+ return x
+
def setvar(self, var, val):
"""Set a default script variable.
"""
else:
print >>sys.stderr, "Error: Unknown option:", k
self.usage()
- return args
+ xargs = []
+ for arg in args:
+ (k, v) = arg.split('=', 1)
+ for opt in self.options:
+ if opt.specify(k, v): break
+ else:
+ xargs.append(arg)
+ return xargs
def short_opts(self):
"""Get short options specifier for getopt.
def usage(self):
print 'Usage: ', self.argv[0], self.use or 'OPTIONS'
for opt in self.options:
+ print
opt.show()
def load_defaults(self, help=0):
globals = {}
locals = {}
locals.update(self.vars)
- cmd = '\n'.join(["import sys",
- "import os",
- "import os.path",
- "from xen.xm.help import Vars",
- "from xen.util import ip",
- "xm_file = '%s'" % defaults,
- "xm_help = %d" % help,
- "xm_vars = Vars(xm_file, xm_help, locals())",
- ])
+ cmd = '\n'.join(self.imports +
+ [ "from xen.xm.help import Vars",
+ "xm_file = '%s'" % defaults,
+ "xm_help = %d" % help,
+ "xm_vars = Vars(xm_file, xm_help, locals())"
+ ])
exec cmd in globals, locals
try:
execfile(defaults, globals, locals)
except:
if not help: raise
- if help: return
+ if help:
+ print 'The following imports are done automatically:'
+ for x in self.imports:
+ print x
+ return
# Extract the values set by the script and set the corresponding
# options, if not set on the command line.
vtypes = [ types.StringType,
"""Set an option false."""
opt.set(0)
+def set_bool(opt, k, v):
+ """Set a boolean option.
+ """
+ if v in ['yes']:
+ opt.set(1)
+ elif v in ['no']:
+ opt.set(0)
+ else:
+ opt.opts.err('Invalid value:' +v)
+
+
def set_value(opt, k, v):
"""Set an option to a valoue."""
opt.set(v)
def set_var(opt, k, v):
"""Set a default script variable.
"""
- (var, val) = v.strip().split('=')
+ (var, val) = v.strip().split('=', 1)
opt.opts.setvar(var.strip(), val.strip())